package net.neptech.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.neptech.bo.RoleBo;
import net.neptech.exception.BusinessException;
import net.neptech.mapper.RoleMapper;
import net.neptech.mapper.RoleMenuMapper;
import net.neptech.mapper.StaffRoleMapper;
import net.neptech.model.sys.Role;
import net.neptech.model.sys.RoleMenu;
import net.neptech.model.sys.StaffRole;
import net.neptech.page.PageQuery;
import net.neptech.page.TableDataInfo;
import net.neptech.service.RoleService;
import net.neptech.utils.BeanCopyUtils;
import net.neptech.utils.StringUtils;
import net.neptech.vo.RoleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: liyuxiang
 * @Date: 2025/8/14 13:52
 * @Description: TODO
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    RoleMenuMapper roleMenuMapper;
    @Autowired
    StaffRoleMapper staffRoleMapper;

    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<Role> perms = roleMapper.selectRolePermissionByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (Role perm : perms) {
            if (StringUtils.isNotNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public TableDataInfo<RoleVo> selectPageRoleList(PageQuery pageQuery) {
        Page<RoleVo> roleVoPage = roleMapper.selectPageRoleList(pageQuery.build());
        return TableDataInfo.build(roleVoPage);
    }

    @Override
    @Transactional
    public void updateRole(RoleBo roleBo) {
        roleMapper.updateById(BeanCopyUtils.copyBean(roleBo, Role.class));
        roleMenuMapper.delete(new LambdaQueryWrapper<>(RoleMenu.class).eq(RoleMenu::getRoleId, roleBo.getRoleId()));
        Arrays.stream(roleBo.getMenuIds()).forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleBo.getRoleId());
            roleMenuMapper.insert(roleMenu);
        });
    }

    @Override
    public void changeStatus(RoleVo roleVo) {
        roleMapper.changeStatus(roleVo);
    }

    @Override
    @Transactional
    public void insertRole(RoleBo roleVo) {
        //1.判断角色名roleName是否存在
        Role existsRoleName = roleMapper.selectOne(new LambdaQueryWrapper<>(Role.class).eq(Role::getRoleName, roleVo.getRoleName()));
        if (existsRoleName != null) {
            throw new BusinessException(400, "新增角色'" + roleVo.getRoleName() + "'失败，角色名称已存在");
        }
        //2.判断角色roleKey是否存在
        Role existsRoleKey = roleMapper.selectOne(new LambdaQueryWrapper<>(Role.class).eq(Role::getRoleKey, roleVo.getRoleKey()));
        if (existsRoleKey != null) {
            throw new BusinessException(400, "新增角色'" + roleVo.getRoleKey() + "'失败，角色权限已存在");
        }
        //插入角色信息，并向role_menu中间表插入插入数据
        Role role = BeanCopyUtils.copyBean(roleVo, Role.class);
        roleMapper.insert(role);
        Long roleId = role.getRoleId();
        Arrays.stream(roleVo.getMenuIds()).forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setId(null);
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleId);
            roleMenuMapper.insert(roleMenu);
        });
    }

    @Override
    @Transactional
    public void deleteRoleByIds(Long[] roleIds) {
        //判断角色是否被用户使用
        for (Long roleId : roleIds) {
            int count = Math.toIntExact(staffRoleMapper.selectCount(new LambdaQueryWrapper<>(StaffRole.class).eq(StaffRole::getRoleId, roleId)));
            if (count > 0) {
                throw new BusinessException(400, "删除角色失败，角色已分配给用户");
            }
        }
        Arrays.stream(roleIds).forEach(roleId -> {
            roleMapper.deleteById(roleId);
            roleMenuMapper.delete(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId, roleId));
        });
    }

    @Override
    public RoleVo selectRoleById(Long roleId) {

        return BeanCopyUtils.copyBean(roleMapper.selectById(roleId), RoleVo.class);
    }

    @Override
    public List<RoleVo> selectRoleAll() {
        return BeanCopyUtils.copyBeanList(roleMapper.selectList(new LambdaQueryWrapper<>(Role.class)), RoleVo.class);
    }

    @Override
    public List<Long> selectRoleByStaffId(Long staffId) {
        return staffRoleMapper.selectList(new LambdaQueryWrapper<>(StaffRole.class).eq(StaffRole::getStaffId, staffId)).stream().map(StaffRole::getRoleId).collect(Collectors.toList());
    }

}
